#include "coroutine_function.h"
#include <unistd.h>
#include <errno.h>

#include "tinyrpc/base/coroutine/coroutine.h"
#include "tinyrpc/net/event.h"
#include "tinyrpc/net/eventloop.h"
#include "event_manager.h"
#include <string.h>
#include <iostream>
// ssize_t read(int fd, void *buf, size_t count);
/**
 * @brief  fd一定是socket 或者pipe
 */

/**
 * 此代码是对 read, write, accept, connected的封装
 * 代码对只会对一种请做处理 returnValue == -1 && errno == EAGAIN
 *      这种情况下表示没有数据可以处理，此时应该将当前协程重新注册到epoll红黑树里面
 *      接着退出
 * 
 * 对于 其他的情况 如 returnValue = 0 不做处理， 这些应该是上一级应用来处理
 */
namespace TinyRPC{



ssize_t coroutine_read(int fd, void *buf, size_t count){
    while (1)
    {
        int len = read(fd, buf, count);
        if(len>0){
            return len;
        }
        // 暂时没有数据可读
        else if(len== -1 && errno == EAGAIN){
          
            //Event readEvent(fdPtr);
           
            EventPtr readEvent = EventManager::GetInstance().getEventPtr(fd);
            Task task = Task(Coroutine::CurrentCoroutine());

            auto func = [&](){
                readEvent->getOwnerChannel()->updateEvent(ReadEvent, task, EventLoop::CurrentEventLoop());
            };

            EventLoop::CurrentEventLoop()->runInLoop(Task(func, false));

            Coroutine::Yield();
        }
        else if(len == 0){
            return 0;
        }
    }
}

ssize_t coroutine_write(int fd, const void *buf, size_t count){
    while (1)
    {
        int len = write(fd, buf, count);
        if(len>0){
            return len;
        }
        // 暂时没有数据可读
        if(len== -1 && errno == EAGAIN){
   
            //Event writeEvent(fdPtr);
            EventPtr writeEvent = EventManager::GetInstance().getEventPtr(fd);
            Task task = Task(Coroutine::CurrentCoroutine());

            auto func = [&](){
                writeEvent->getOwnerChannel()->updateEvent(WriteEvent, task, EventLoop::CurrentEventLoop());
            };


            EventLoop::CurrentEventLoop()->runInLoop(Task(func, false));

            Coroutine::Yield();
        }else{
            return len;
        }
    }
}

int coroutine_accept(int __fd, struct sockaddr * __addr, socklen_t * __addr_len){
    while (1)
    {
        int len = ::accept( __fd,  __addr, __addr_len);
        // if(len == -1){
        //     std::cout<<strerror(errno)<<std::endl;
        // }
        // 暂时没有数据可读
        if(len== -1 && errno == EAGAIN){
      
            //Event readEvent(fdPtr);
            EventPtr readEvent = EventManager::GetInstance().getEventPtr(__fd);
            Task task = Task(Coroutine::CurrentCoroutine());

            auto func = [&](){
                readEvent->getOwnerChannel()->updateEvent(ReadEvent, task, EventLoop::CurrentEventLoop());
            };

            EventLoop::CurrentEventLoop()->runInLoop(Task(func, false));

            Coroutine::Yield();
        }else{
            return len;
        }
    }
}
int coroutine_connect(int __fd, const struct sockaddr *__addr, socklen_t __len){
    while (1)
    {
        int len = connect( __fd,  __addr, __len);
        if(len == -1){
            std::cout<<strerror(errno)<<std::endl;
        }
        // 暂时没有数据可读
        if(len== -1 && errno == EAGAIN){
            EventPtr readEvent = EventManager::GetInstance().getEventPtr(__fd);
            Task task = Task(Coroutine::CurrentCoroutine());

            auto func = [&](){
                readEvent->getOwnerChannel()->updateEvent(ReadEvent, task, EventLoop::CurrentEventLoop());
            };

            EventLoop::CurrentEventLoop()->runInLoop(Task(func, false));

            Coroutine::Yield();
        }else{
            return len;
        }
        
        
        
    }
}


void coroutine_sleep(unsigned int __seconds){
    EventLoop::CurrentEventLoop()->runAfter(__seconds , Task(Coroutine::CurrentCoroutine()));
    Coroutine::Yield();
}


}